package com.serve.oa.controller;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.serve.oa.common.lang.Const;
import com.serve.oa.common.lang.Result;
import com.serve.oa.dto.*;
import com.serve.oa.entity.*;
import com.serve.oa.service.SysUserService;
import com.serve.oa.service.TblFlowNodeService;
import com.serve.oa.service.TblTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.cmmn.api.CmmnTaskService;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskLogEntry;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author __tyw
 * @since 2022-12-12
 */
@Slf4j
@Api(tags = "流程模块")
@RestController
@RequestMapping("/task")
public class TblTaskController extends BaseController {

    @Autowired
    TblTaskService tblTaskService;

    @Autowired
    TblFlowNodeService tblFlowNodeService;

    @Autowired
    RuntimeService runtimeService;


    @Autowired
    TaskService taskService;


    @Autowired
    HistoryService historyService;


    @Autowired
    RepositoryService repositoryService;

    @Autowired
    ProcessEngine processEngine;


    @Autowired
    IdentityService identityService;


    @ApiOperation(value = "单个流程详情")
    @GetMapping("/deailf/{id}")
    //@Transactional
    @RequiresPermissions("tbl:task:list")
    public Result taskds(@PathVariable("id") String id){



        List<HistoricVariableInstance> variable1 =  historyService.createHistoricVariableInstanceQuery().processInstanceId(id).list();


        Map variable = new HashMap<>();
        variable1.stream().forEach(i->{
            variable.put(i.getVariableName(),i.getValue());
        });

       // Map<String, Object> variable =  runtimeService.getVariables(id);
        Set<String> set1 = new HashSet<String>();
        set1.add("userTask");
         List<HistoricTaskInstance> logs = historyService.createHistoricTaskInstanceQuery().processInstanceId(id).finished().orderByHistoricTaskInstanceEndTime().asc().list();


        System.out.println();
        List<HistoricTaskLogEntry> logs1 = historyService.createHistoricTaskLogEntryQuery().processInstanceId(id).list();


        Map map = new HashMap<>();
        map.put("detail",tblTaskService.getFlowDeatil(variable));
        List<Map<String, Object>> sd = new ArrayList<>();

        logs.stream().forEach(i->{

            List<Comment> clist = taskService.getTaskComments(i.getId());
           // //System.out.println(taskService.getProcessInstanceComments(i.getProcessInstanceId()));
            Map map1 = new HashMap<>();
            map1.put("time",i.getEndTime());
            map1.put("name",i.getName());
            map1.put("name1",i.getAssignee());
            map1.put("tips",clist.stream().map(Q->Q.getFullMessage()));
           // map1.put("name3",i.g());
            sd.add(map1);
        });
        map.put("log",sd);
        map.put("log1",logs);
        map.put("log2",logs1);





  /*      TblTask task = tblTaskService.getOne(new QueryWrapper<TblTask>().eq("task_id",id));

        List<TaskDto> list = tblTaskService.myHandleTask(this.curUser().getId());



        Boolean  isMyTask = list.stream().anyMatch(item->item.getTaskId() == id);



        if(task.getUserId() != this.curUser().getId().intValue() && !isMyTask){

            return Result.succ("你没有权限查看别人的");
        }



        List<TblFlowNode> line = tblFlowNodeService.list(new QueryWrapper<TblFlowNode>().eq("flow_no",task.getFlowNo()).orderByAsc("cur_node"));

        line.forEach(i->{
            if(i.getCurNode() > task.getCurNode()){
                i.setIsFin(0);
            }else {
                i.setIsFin(1);
            }
        });
        Map map = new HashMap<>();
        if(task.getFlowNo() == 5){
            map.put("detail",tblTaskService.getLeave(task.getTaskId()));
        }else {
            map.put("detail",tblTaskService.getBxt(task.getTaskId()));
        }



        map.put("line",line);

        map.put("log",tblTaskService.getLog(task.getTaskId()));
        map.put("type",task.getFlowNo());
        map.put("tiem",tblTaskService.getTime("2"));
        // map.put("chaList", tblTaskService.listAll());
*/


        return Result.succ(map);



    }



    @ApiOperation(value = "待我处理的流程")
    @GetMapping("/myfHandleTask")
    @Transactional
    @RequiresPermissions("tbl:task:dcl")
    public Result myHandleTaskf(){


        Page<TaskFlowDto> iPage = this.getPage();
       // //System.out.println(this.curUser().getId());
        String s1 = String.valueOf(this.curUser().getId());

        List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(s1).list();


        List<TaskFlowDto> list = new ArrayList<>();
        for (Task task : tasks) {

            Map<String, Object> variable =  runtimeService.getVariables(task.getProcessInstanceId());

            TaskFlowDto s = new TaskFlowDto();
            s.setId(task.getProcessInstanceId());
            s.setExecutionId(task.getExecutionId());
            s.setName(task.getName());
            s.setFqr((String) variable.get("fqr"));
            s.setProcessInstanceId(task.getProcessInstanceId());
            Date date3 = DateUtil.date(task.getCreateTime());

            s.setCreated(date3.toString());
            list.add(s);
        }

        iPage.setRecords(list);

        return Result.succ(iPage);


    }


    @ApiOperation(value = "审批通过")
    @PostMapping("/ftaskOk/{id}")
    @Transactional
    @RequiresPermissions("tbl:task:dcl")
    public Result taslOks(@PathVariable("id") String id, @RequestBody Map<String, Object> params){




        Task task = taskService.createTaskQuery().processInstanceId(id).singleResult();

        Map<String, Object> map = new HashMap<>();

        map.put("appouy", "同意");
      //  map.put("day", 4);

        taskService.addComment(task.getId(),task.getProcessInstanceId(), (String) params.get("Reason"));
        taskService.setAssignee(task.getId(),this.curUser().getName());
        taskService.complete(task.getId(),map);

        return  Result.succ("审批完成");

    }

    @ApiOperation(value = "驳回")
    @PostMapping("/ftaskNo/{id}")
    @Transactional
    @RequiresPermissions("tbl:task:dcl")
    public Result taslOkss(@PathVariable("id") String id, @RequestBody Map<String, Object> params){




        Task task = taskService.createTaskQuery().processInstanceId(id).singleResult();

        Map<String, Object> map = new HashMap<>();

        map.put("appouy", "拒绝");
        //  map.put("day", 4);

        taskService.addComment(task.getId(),task.getProcessInstanceId(), (String) params.get("Reason"));
        taskService.setAssignee(task.getId(),this.curUser().getName());
        taskService.complete(task.getId(),map);

        Task task1 = taskService.createTaskQuery().processInstanceId(id).singleResult();
        String fbr = (String) taskService.getVariable(task1.getId(),"fqr");
        taskService.addCandidateUser(task1.getId(), fbr);


        return  Result.succ("拒绝完成");

    }

    @PostMapping("/mytask/deletea")
    @ResponseBody
    public Result delet1e(@RequestBody Map<String, String> params) {

        //删除部署的流程 第一个参数是ID，如果部署的流程启动了就不允许删除了
        //repositoryService.deleteDeployment("1");
        //第二个参数是级联删除，如果流程启动了，相关的任务一并删除掉(act_re_deployment id=2501)
        //runtimeService.deleteProcessInstance("2696cd67-a3a2-11ed-8676-56b2bbb99e44","不要了");
        //runtimeService.deleteProcessInstance("981f58bc-a39c-11ed-af15-56b2bbb99e44","不要了");

        Task task = taskService.createTaskQuery().processInstanceId(String.valueOf(params.get("id"))).singleResult();
        taskService.addComment(task.getId(),task.getProcessInstanceId(), "删除了流程");
        taskService.setAssignee(task.getId(),this.curUser().getName());
        runtimeService.deleteProcessInstance(String.valueOf(params.get("id")),"不要了");


        //taskService.deleteTask();
        //taskService.deleteTask(String.valueOf(params.get("id")),true);

        return Result.succ("成功");
    }

    @GetMapping("/pic/{processId}")
    public void showPic(HttpServletResponse resp,@PathVariable String processId) throws Exception {


        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
      //  //System.out.println(pi.toString());
        if (pi == null) {
            return;
        }
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(processId)
                .list();

        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        /**
         * 生成流程图
         */
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, false);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {

            resp.setContentType("image/png");
            out = resp.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }


    @ApiOperation(value = "发起flow流程")
    @PostMapping("/flowadd/5")
    @Transactional
    @RequiresPermissions("tbl:task:add")
    public Result addf(@Validated @RequestBody LeaveFlowDto leaveDto){




        tblTaskService.addLeaveFlow(leaveDto);


        HashMap<String, Object> map = new HashMap<>();
        map.put("owner",this.curUser().getId().toString());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjiadan");
        runtimeService.setVariable(processInstance.getId(), "fqr", this.curUser().getId().toString());
        runtimeService.setVariable(processInstance.getId(), "TableType", 1);
        runtimeService.setVariable(processInstance.getId(), "formId", leaveDto.getId());
        runtimeService.setVariable(processInstance.getId(), "day", leaveDto.getDay());




        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();


        taskService.setAssignee(task.getId(),this.curUser().getName());
        taskService.addComment(task.getId(),task.getProcessInstanceId(), "发起请假申请");
        taskService.complete(task.getId());




        return Result.succ("成功");


    }


    @ApiOperation(value = "cz我的流程")
    @GetMapping("/mytaskflow")
    @Transactional
    @RequiresPermissions("tbl:task:list")
    public Result mylists(){


        //System.out.println(323);



        int current = ServletRequestUtils.getIntParameter(req, "cuurent", 1);
        int size = ServletRequestUtils.getIntParameter(req, "size", 5);


        List<Task>  tasks = taskService.createTaskQuery().processVariableValueEquals("fqr",this.curUser().getId().toString()).list();

        List<HistoricProcessInstance> tasks3 =  historyService.createHistoricProcessInstanceQuery().variableValueEquals("fqr",this.curUser().getId().toString()).orderByProcessInstanceStartTime().desc().list();

        List<HistoricProcessInstance> tasks1 = tasks3.stream().skip((current - 1) *size).limit(size).collect(Collectors.toList());

        //log.info(tasks1.toString());



        Page iPage = this.getPage();
        iPage.setTotal(tasks3.size());

        List<TaskFlowDto> list = new ArrayList<>();
       for (HistoricProcessInstance task : tasks1) {

           List<HistoricVariableInstance> sad = historyService.createHistoricVariableInstanceQuery().processInstanceId(task.getId()).list();



            TaskFlowDto s = new TaskFlowDto();
            s.setId(task.getId());


            s.setName(task.getName());

            if(tasks.isEmpty()){
                s.setZt("完成");
            }else {

                boolean sj = tasks.stream().anyMatch(i -> i.getProcessInstanceId().equals(task.getId()));
                if(sj){
                    s.setZt("进行中");
                }else {
                    s.setZt("完成");
                }
            }


           s.setProcessInstanceId(task.getId());
           Date date3 = DateUtil.date(task.getStartTime());

           s.setCreated(date3.toString());
            for (HistoricVariableInstance hvi : sad) {
               // //System.out.println(hvi.getVariableName() +  hvi.getValue());
                if(Objects.equals(hvi.getVariableName(), "fqr")){
                    s.setFqr((String) hvi.getValue());
                }


            }
            list.add(s);


        }


      iPage.setRecords(list);


        return Result.succ(iPage);





    }


    @ApiOperation(value = "发起流程")
    @PostMapping("/add/5")
    @Transactional
    @RequiresPermissions("tbl:task:add")
    public Result add(@Validated @RequestBody LeaveDto leaveDto){

        int id = tblTaskService.add(5L, Math.toIntExact(this.curUser().getId()));

        leaveDto.setTaskId(id);


        tblTaskService.addLeave(leaveDto);

        TblLog tblLog = new TblLog();
        tblLog.setTips("发起请假申请单");
        tblLog.setTime(LocalDateTime.now());
        tblLog.setType(0);
        tblLog.setUserName(this.curUser().getName());
        tblLog.setTaskId(id);

        tblTaskService.inLog(tblLog);

        return Result.succ("成功");


    }


    @ApiOperation(value = "下载")
    @GetMapping("/file/{flag}")
    @RequiresPermissions("tbl:task:list")
    public void getFiles(@PathVariable String flag, HttpServletResponse response) {
        OutputStream os;  // 新建一个输出流对象
        String basePath = System.getProperty("user.dir") + "/files/";  // 定于文件上传的根路径
        List<String> fileNames = FileUtil.listFileNames(basePath);  // 获取所有的文件名称
        String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");  // 找到跟参数一致的文件
        try {
            if (StrUtil.isNotEmpty(fileName)) {
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                response.setContentType("application/octet-stream");
                byte[] bytes = FileUtil.readBytes(basePath + fileName);  // 通过文件的路径读取文件字节流
                os = response.getOutputStream();   // 通过输出流返回文件
                os.write(bytes);
                os.flush();
                os.close();
            }
        } catch (Exception e) {
            //System.out.println("文件下载失败");
        }
    }


    @ApiOperation(value = "发起报销流程")
    @PostMapping("/add/6")
    @Transactional
    @RequiresPermissions("tbl:task:add")
    public Result addbx(BxtDto bxtDto) throws IOException, InterruptedException {



     String sta = "";
     for(MultipartFile item :bxtDto.getFiles()){
        // //System.out.println(System.getProperty("user.dir"));

            String originalFilename = item.getOriginalFilename();  // 获取源文件的名称
            String flag = IdUtil.fastSimpleUUID(); // 定义文件的唯一标识（前缀）


            String rootFilePath = System.getProperty("user.dir") + "/files/" + flag + "_" + originalFilename;  // 获取上传的路径


            sta = sta + flag + "_" + originalFilename + ";";
            File saveFile = new File(rootFilePath);
            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            FileUtil.writeBytes(item.getBytes(), rootFilePath);  // 把文件写入到上传的路径

        }
        int id = tblTaskService.add(6L, Math.toIntExact(this.curUser().getId()));


        BxtLeave bxtLeave = new BxtLeave();

        bxtLeave.setFiled(sta);
        bxtLeave.setTaskId(id);
        bxtLeave.setReason(bxtDto.getReason());


        tblTaskService.addBxt(bxtLeave);

        TblLog tblLog = new TblLog();
        tblLog.setTips("发起报销申请单");
        tblLog.setTime(LocalDateTime.now());
        tblLog.setType(0);
        tblLog.setUserName(this.curUser().getName());
        tblLog.setTaskId(id);

        tblTaskService.inLog(tblLog);
        tblTaskService.ybdy();//异步任务

        return Result.succ("成功");


    }

    @ApiOperation(value = "我的流程")
    @GetMapping("/mytask")
    @Transactional
    @RequiresPermissions("tbl:task:list")
    public Result mylist(){


        Page<TaskDto> iPage = this.getPage();


        return Result.succ(tblTaskService.getMytaskPage(iPage,this.curUser().getId()));


    }


    @ApiOperation(value = "待我处理的流程")
    @GetMapping("/myHandleTask")
    @Transactional
    @RequiresPermissions("tbl:task:dcl")
    public Result myHandleTask(){


        Page<TaskDto> iPage = this.getPage();
        List<TaskDto> list = tblTaskService.myHandleTask(this.curUser().getId());

        int current = ServletRequestUtils.getIntParameter(req, "cuurent", 1);
        int size = ServletRequestUtils.getIntParameter(req, "size", 5);

        List<TaskDto> list1 = list.stream().skip((current - 1) *size).limit(size).collect(Collectors.toList());

        iPage.setRecords(list1);
        iPage.setTotal(list.size());
        iPage.setCurrent(current);
        iPage.setSize(size);
        return Result.succ(iPage);


    }
    @ApiOperation(value = "审批通过")
    @PostMapping("/taskOk/{id}")
    @Transactional
    @RequiresPermissions("tbl:task:dcl")
    public Result taslOk(@PathVariable("id") Integer id, @RequestBody Map<String, Object> params){

        TblTask task = tblTaskService.getOne(new QueryWrapper<TblTask>().eq("task_id",id));
        List<TaskDto> list = tblTaskService.myHandleTask(this.curUser().getId());

        Boolean  isMyTask = list.stream().anyMatch(item->item.getTaskId() == id);



        if(task.getUserId() != this.curUser().getId().intValue() && !isMyTask){

            return Result.succ("你没有权限查看别人的");
        }



        Boolean isOK = tblTaskService.nextNode(id,task.getCurNode(),task.getFlowNo());


        if(isOK){

            TblLog tblLog = new TblLog();
            tblLog.setTips("审批通过"+ params.get("Reason"));
            tblLog.setTime(LocalDateTime.now());
            tblLog.setType(1);
            tblLog.setUserName(this.curUser().getName());
            tblLog.setTaskId(id);

            tblTaskService.inLog(tblLog);

            return Result.succ("操作成功");
        }else {
            return Result.succ("已经最后了");
        }



    }


    @PostMapping("/mytask/delete")
    @ResponseBody
    @Transactional
    @RequiresPermissions("tbl:task:del")
    public Result delete(@RequestBody Map<String, Integer> params) {




        TblTask task = tblTaskService.getOne(new QueryWrapper<TblTask>().eq("task_id",params.get("id")));

        if(task.getUserId() != this.curUser().getId().intValue()){

            return Result.succ(403,"你没有权限删除别人的",null);
        }

        userService.removeById(params.get("id"));
        tblTaskService.delmylist(String.valueOf(params.get("id")));

        return Result.succ(200,"删除了",null);
    }


    @ApiOperation(value = "单个流程详情")
    @GetMapping("/deail/{id}")
    //@Transactional
    @RequiresPermissions("tbl:task:list")
    public Result taskd(@PathVariable("id") Integer id){
        TblTask task = tblTaskService.getOne(new QueryWrapper<TblTask>().eq("task_id",id));

        List<TaskDto> list = tblTaskService.myHandleTask(this.curUser().getId());



        Boolean  isMyTask = list.stream().anyMatch(item->item.getTaskId() == id);



        if(task.getUserId() != this.curUser().getId().intValue() && !isMyTask){

            return Result.succ("你没有权限查看别人的");
        }


        List<TblFlowNode> line = tblFlowNodeService.list(new QueryWrapper<TblFlowNode>().eq("flow_no",task.getFlowNo()).orderByAsc("cur_node"));

        line.forEach(i->{
            if(i.getCurNode() > task.getCurNode()){
                i.setIsFin(0);
            }else {
                i.setIsFin(1);
            }
        });
        Map map = new HashMap<>();
        if(task.getFlowNo() == 5){
            map.put("detail",tblTaskService.getLeave(task.getTaskId()));
        }else {
            map.put("detail",tblTaskService.getBxt(task.getTaskId()));
        }



        map.put("line",line);

        map.put("log",tblTaskService.getLog(task.getTaskId()));
        map.put("type",task.getFlowNo());
        map.put("tiem",tblTaskService.getTime("2"));
       // map.put("chaList", tblTaskService.listAll());



        return Result.succ(map);



    }

}
